package com.hzlj.position.config.rest;

import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.http.HttpRequest;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fz.common.base.core.JsonUtils;
import com.fz.common.base.core.LocateUtils;
import com.fz.common.base.exception.PubException;
import com.hzlj.position.config.config.PositionConfig;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * 经纬度反解析
 */
@Slf4j
@Service
public class LonLatAddressRest {
    /**
     * 位置详情_超时时间设置
     */
    private static final int LOCATE_CONNECT_TIMEOUT = 10000;
    /**
     * 位置详情_读取超时时间
     */
    private static final int LOCATE_READ_TIMEOUT = 20000;
    /**
     * 天地图参数
     */
    private static final String TIAN_DI_TU_PARAMS = "postStr={'lon':%s,'lat':%s,'ver':1}&type=geocode&tk=%s";

    @Resource
    private PositionConfig positionConfig;

    public String getAddress(String longitude, String latitude) {
        return getAddress(longitude, latitude, 1);
    }

    private String getAddress(String longitude, String latitude, int retryCount) {
        PositionConfig.LonLat lonLat = positionConfig.getLonLat();
        try {
            switch (lonLat.type(retryCount)) {
                case "gd":
                    return gd(longitude, latitude);
                case "tianditu":
                    return tianditu(longitude, latitude);
                default:
                    return "没有配置地址解析器";
            }
        } catch (PubException e) {
            log.warn("位置解析失败；longitude:{},latitude:{},retryCount:{},error={}", longitude, latitude, retryCount, e.getMsg());
        } catch (Exception e) {
            log.error("位置解析失败；longitude:{},latitude:{},retryCount:{}", longitude, latitude, retryCount, e);
        }
        if (retryCount >= positionConfig.getLonLat().getRetryCount()) {
            return String.format("解析位置信息失败:经纬度(%s,%s)", longitude, latitude);
        }
        return getAddress(longitude, latitude, ++retryCount);
    }


    /**
     * 高德
     */
    private String gd(String longitude,
                      String latitude) throws UnsupportedEncodingException {
        double[] coordinate = LocateUtils.gps84ToGcj02(Double.parseDouble(longitude), Double.parseDouble(latitude));
        String body = HttpRequest.post(positionConfig.getLonLat().getGdUrl())
                .setConnectionTimeout(LOCATE_CONNECT_TIMEOUT)
                .setReadTimeout(LOCATE_READ_TIMEOUT)
                .form("locateType", "gd")
                .form("longitude", String.valueOf(coordinate[0]))
                .form("latitude", String.valueOf(coordinate[1]))
                .execute()
                .body();
        JsonNode jsonNode = JsonUtils.json2jsonNode(body);
        if (jsonNode != null
                && jsonNode.get("success").asBoolean(false)) {
            return URLDecoder.decode(jsonNode.get("position").asText(), "UTF-8");
        }
        throw new PubException(body);
    }

    /**
     * 天地图
     */
    private String tianditu(String longitude,
                            String latitude) {
        String params = String.format(TIAN_DI_TU_PARAMS, longitude, latitude, positionConfig.getLonLat().getTiandituKey());
        String body = HttpRequest.get(positionConfig.getLonLat().getTiandituUrl() + "?" + URLEncodeUtil.encode(params))
                .setConnectionTimeout(LOCATE_CONNECT_TIMEOUT)
                .setReadTimeout(LOCATE_READ_TIMEOUT)
                .execute()
                .body();
        TianDiTuResult result = JsonUtils.json2obj(body, TianDiTuResult.class);
        if (result.success()) {
            return result.getResult().getFormattedAddress();
        }
        throw new PubException(result.msg);
    }

    @NoArgsConstructor
    @Data
    private static class TianDiTuResult {
        @JsonProperty("msg")
        private String msg;
        @JsonProperty("status")
        private String status;
        @JsonProperty("result")
        private Address result;

        public boolean success() {
            return "0".equals(status);
        }


        @NoArgsConstructor
        @Data
        public static class Address {
            @JsonProperty("formatted_address")
            private String formattedAddress;
        }
    }

    public static void main(String[] args) {
        LonLatAddressRest lonLatAddressRest = new LonLatAddressRest();
        PositionConfig positionConfig1 = new PositionConfig();
        PositionConfig.LonLat lonLat = new PositionConfig.LonLat();
        lonLat.setTypes("tianditu,gd");
        lonLat.setGdUrl("http://139.196.126.188:19999/LocateCore/locate/getLocate");
        lonLat.setTiandituUrl("https://api.tianditu.gov.cn/geocoder");
        lonLat.setTiandituKey("644e56da6a864e168e70687b34133c2c");
        positionConfig1.setLonLat(lonLat);
        lonLatAddressRest.positionConfig = positionConfig1;

        System.out.println(lonLatAddressRest.getAddress(
                "123.327348", "41.416236"
        ));
    }
}
